/****************************************************************
 * <strong>MFListenerManager</strong>
 *
 * <p>
 * MFListenerManager
 * </p>
 *
 * @author AndyZhang 2011 cnet2001@163.com
 * @version 0.1
 * ToDo:
 ***************************************************************/
package com.thinkwide.data.listener;

import com.thinkwide.data.ormapping.MFDbTypeTransfer;
import com.thinkwide.data.ormapping.MFReflect;
import com.thinkwide.data.core.MFConvert;
import com.thinkwide.data.core.MFPath;
import com.thinkwide.data.core.MFString;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;

public class MFListenerManager extends java.util.TimerTask {

    private List<MFListenerTaskItem> items;
    private HttpServletRequest request;
    private ServletContext application;
    private HttpServletResponse response;

    public MFListenerManager() {
        items = new ArrayList<MFListenerTaskItem>();
    }

    public MFListenerManager(HttpServletRequest request, HttpServletResponse response) {
        this();
        updateState(request, response);
    }

    public void updateState(HttpServletRequest request, HttpServletResponse response) {
        this.request = request;
        this.response = response;
    }

    public boolean prepareProperty(Class<?> classType, Object obj) throws Throwable {

        Enumeration params = request.getParameterNames();
        while (params.hasMoreElements()) {
            String name = (String) params.nextElement();
            String value = request.getParameter(name);

            if (MFString.notNullOrEmpty(name) && MFReflect.isHaveProperty(obj, name)) {
                Class<?> type = MFReflect.getPropertyType(obj, name);
                Object typedValue = MFDbTypeTransfer.toJavaType(type, value);
                MFReflect.setProperty(obj, name, typedValue);

            }
        }
        return true;
    }

    public Object createTask(MFListenerTaskItem item) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
        Class<?> c = Class.forName(item.getClassName());

        //参数类型数组
        //  Class[] parameterTypes=...{String.class};
        //根据参数类型获取相应的构造函数
        //  java.lang.reflect.Constructor constructor=c.getConstructor(parameterTypes);
        //参数数组
        //  Object[] parameters=...{"1"};
        //根据获取的构造函数和参数，创建实例
        //  Object o=constructor.newInstance(parameters);


        Object obj = c.newInstance();
        return obj;
    }

    public boolean runMethod(MFListenerTaskItem item) throws Throwable {
        if (item != null) {
            Class<?> c = Class.forName(item.getClassName());

            Object obj = c.newInstance();

            //prepareProperty(c,obj);

            String methodName = item.getMethod();
            Method method = c.getDeclaredMethod(methodName, null);

            Object value = method.invoke(obj, null);

        }
        return false;
    }


    public String CheckPath(String url) {
        if (MFString.notNullOrEmpty(url) && !url.startsWith(MFPath.useparator)) {
            url = MFPath.useparator + url;
        }
        return url;
    }

    public String getAttrValue(Element item, String name) {
        Attribute attr = item.attribute(name);
        if (attr != null) {
            String text = attr.getText();
            return text;
        }
        return null;
    }

    public boolean loadConfig(String filePath) throws DocumentException {
        File file = new File(filePath);

        SAXReader reader = new SAXReader();
        Document doc = reader.read(file);
        Element root = doc.getRootElement();

        //load action
        for (Iterator<?> i = root.elementIterator("listener"); i.hasNext(); ) {
            Element listenerItem = (Element) i.next();
            String listenerName = getAttrValue(listenerItem, "name");
            String listenerType = getAttrValue(listenerItem, "type");

            for (Iterator<?> j = listenerItem.elementIterator("task"); j.hasNext(); ) {
                MFListenerTaskItem item = new MFListenerTaskItem();
                Element taskItem = (Element) j.next();

                String taskName = getAttrValue(taskItem, "name");
                String tasktype = getAttrValue(taskItem, "tasktype");

                item.setName(taskName);
                item.setType(listenerType);
                item.setTaskType(tasktype);

                for (Iterator<?> k = taskItem.elementIterator("param"); k.hasNext(); ) {
                    Element paramItem = (Element) k.next();

                    String paramName = getAttrValue(paramItem, "name");

                    if (MFString.compareNoCase(paramName, "enable")) {
                        item.setEnable(paramItem.getText());
                    }

                    if (MFString.compareNoCase(paramName, "className")) {
                        item.setClassName(paramItem.getText());
                    }

                    if (MFString.compareNoCase(paramName, "circleType")) {
                        item.setCircleType(paramItem.getText());
                    }

                    if (MFString.compareNoCase(paramName, "interval")) {
                        item.setInterval(MFConvert.strToIntDef(paramItem.getText(), 0));
                    }

                    if (MFString.compareNoCase(paramName, "method")) {
                        item.setMethod(paramItem.getText());
                    }

                    if (MFString.compareNoCase(paramName, "param")) {
                        item.setParam(paramItem.getText());
                    }

                }

                items.add(item);
            }
        }

        return true;
    }

    @Override
    public void run() {
        // TODO Auto-generated method stub
        for (MFListenerTaskItem item : items) {
            if (MFString.compareNoCase(item.getEnable(), "true") && MFString.compareNoCase(item.getType(), "ServletContext")) {
                if (MFString.compareNoCase(item.getTaskType(), "task")) {
                    if (item.getInstant() == null) {
                        try {
                            item.setInstant(this.createTask(item));
                            MFServletContextListenerTask task = (MFServletContextListenerTask) item.getInstant();
                            task.setInterval(item.getInterval());
                            task.setApplication(application);


                        } catch (Exception e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }
                    } else {
                        ((MFServletContextListenerTask) item.getInstant()).run();
                    }

                }

                if (MFString.compareNoCase(item.getTaskType(), "method")) {

                    try {
                        this.runMethod(item);
                    } catch (Throwable e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }

                }


            }
        }
    }

    public void setApplication(ServletContext application) {
        this.application = application;
    }

    public ServletContext getApplication() {
        return application;
    }


}
